initialise_gdb(); /* could be moved earlier */
+ iommu_setup(); /* setup iommu if available */
+
do_initcalls();
sort_main_extable();
{
u32 lo, hi;
+ if ( !iommu_supports_eim() )
+ return;
+
rdmsr(MSR_IA32_APICBASE, lo, hi);
if ( !(lo & MSR_IA32_APICBASE_EXTD) )
{
else
printk("x2APIC mode enabled by BIOS.\n");
- x2apic_enabled = 1;
+ if ( !x2apic_enabled )
+ {
+ x2apic_enabled = 1;
+ genapic = &apic_x2apic;
+ printk(KERN_INFO "Switched to APIC driver %s.\n",
+ genapic->name);
+ }
}
void __init init_apic_mappings(void)
*/
if (boot_cpu_physical_apicid == -1U)
boot_cpu_physical_apicid = get_apic_id();
+ x86_cpu_to_apicid[0] = get_apic_id();
+ cpu_2_logical_apicid[0] = get_logical_apic_id();
init_ioapic_mappings();
}
#include <asm/apicdef.h>
#include <asm/genapic.h>
-extern struct genapic apic_x2apic;
extern struct genapic apic_summit;
extern struct genapic apic_bigsmp;
extern struct genapic apic_default;
struct genapic *genapic;
struct genapic *apic_probe[] __initdata = {
- &apic_x2apic,
&apic_summit,
&apic_bigsmp,
&apic_default, /* must be last */
generic_apic_probe();
+ acpi_boot_init();
+
if ( x2apic_is_available() )
enable_x2apic();
- acpi_boot_init();
-
init_cpu_to_node();
if ( smp_found_config )
if ( opt_nosmp )
max_cpus = 0;
+ iommu_setup(); /* setup iommu if available */
+
smp_prepare_cpus(max_cpus);
spin_debug_enable();
return 0;
}
-static int iommu_setup(void)
+int iommu_setup(void)
{
int rc = -ENODEV;
iommu_pv_enabled ? "en" : "dis");
return rc;
}
-__initcall(iommu_setup);
int iommu_get_device_group(struct domain *d, u8 bus, u8 devfn,
XEN_GUEST_HANDLE_64(uint32) buf, int max_sdevs)
struct acpi_table_drhd * drhd = (struct acpi_table_drhd *)header;
void *dev_scope_start, *dev_scope_end;
struct acpi_drhd_unit *dmaru;
+ void *addr;
int ret = 0;
static int include_all = 0;
dprintk(XENLOG_INFO VTDPREFIX, "dmaru->address = %"PRIx64"\n",
dmaru->address);
+ addr = map_to_nocache_virt(0, drhd->address);
+ dmaru->ecap = dmar_readq(addr, DMAR_ECAP_REG);
+
dev_scope_start = (void *)(drhd + 1);
dev_scope_end = ((void *)drhd) + header->length;
ret = acpi_parse_dev_scope(dev_scope_start, dev_scope_end,
struct dmar_scope scope; /* must be first member of struct */
struct list_head list;
u64 address; /* register base address of the unit */
+ u64 ecap;
u8 include_all:1;
struct iommu *iommu;
struct list_head ioapic_list;
} \
} while (0)
+void *map_to_nocache_virt(int nr_iommus, u64 maddr);
+
int vtd_hw_check(void);
void disable_pmr(struct iommu *iommu);
int is_usb_device(u8 bus, u8 devfn);
apicid_to_bdf(apic_id));
}
+int iommu_supports_eim(void)
+{
+ struct acpi_drhd_unit *drhd;
+
+ if ( !iommu_enabled || !iommu_qinval || !iommu_intremap )
+ return 0;
+
+ for_each_drhd_unit ( drhd )
+ if ( !ecap_queued_inval(drhd->ecap) ||
+ !ecap_intr_remap(drhd->ecap) ||
+ !ecap_eim(drhd->ecap) )
+ return 0;
+
+ return 1;
+}
+
static int remap_entry_to_ioapic_rte(
struct iommu *iommu, struct IO_xAPIC_route_entry *old_rte)
{
ir_ctrl->iremap_index = -1;
}
-#if defined(ENABLED_EXTENDED_INTERRUPT_SUPPORT)
+#ifdef CONFIG_X86
/* set extended interrupt mode bit */
ir_ctrl->iremap_maddr |=
- ecap_ext_intr(iommu->ecap) ? (1 << IRTA_REG_EIME_SHIFT) : 0;
+ x2apic_enabled ? (1 << IRTA_REG_EIME_SHIFT) : 0;
#endif
spin_lock_irqsave(&iommu->register_lock, flags);
iommu_flush_iec_global(iommu);
spin_lock_irqsave(&iommu->register_lock, flags);
- /* enable comaptiblity format interrupt pass through */
- gcmd |= DMA_GCMD_CFI;
- dmar_writel(iommu->reg, DMAR_GCMD_REG, gcmd);
-
- IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, dmar_readl,
- (sts & DMA_GSTS_CFIS), sts);
-
/* enable interrupt remapping hardware */
gcmd |= DMA_GCMD_IRE;
dmar_writel(iommu->reg, DMAR_GCMD_REG, gcmd);
#define ecap_queued_inval(e) ((e >> 1) & 0x1)
#define ecap_dev_iotlb(e) ((e >> 2) & 0x1)
#define ecap_intr_remap(e) ((e >> 3) & 0x1)
-#define ecap_ext_intr(e) ((e >> 4) & 0x1)
+#define ecap_eim(e) ((e >> 4) & 0x1)
#define ecap_cache_hints(e) ((e >> 5) & 0x1)
#define ecap_pass_thru(e) ((e >> 6) & 0x1)
#define ecap_snp_ctl(e) ((e >> 7) & 0x1)
unsigned int get_cache_line_size(void);
void cacheline_flush(char *);
void flush_all_cache(void);
-void *map_to_nocache_virt(int nr_iommus, u64 maddr);
u64 alloc_pgtable_maddr(struct acpi_drhd_unit *drhd, unsigned long npages);
void free_pgtable_maddr(u64 maddr);
void *map_vtd_domain_page(u64 maddr);
APICFUNC(acpi_madt_oem_check)
extern struct genapic *genapic;
+extern struct genapic apic_x2apic;
void init_apic_ldr_flat(void);
void clustered_apic_check_flat(void);
#define MAX_APICID 256
extern u32 x86_cpu_to_apicid[];
+extern u32 cpu_2_logical_apicid[];
#define cpu_physical_id(cpu) x86_cpu_to_apicid[cpu]
struct intel_iommu *intel;
};
+int iommu_setup(void);
+int iommu_supports_eim(void);
+
int iommu_add_device(struct pci_dev *pdev);
int iommu_remove_device(struct pci_dev *pdev);
int iommu_domain_init(struct domain *d);